#define GDT_MAX	8192
#define GDT_DIM	8
#define GDT_ENTRY 8

struct x86_TSS {
	unsigned int link;
	unsigned int ESP0;
	unsigned short SS0,__ss0h
	unsigned int esp1;
	unsigned short ss1,__ss1h
	unsigned int esp2;
	unsigned short ss2,__ss2h
	unsigned int cr3;
	unsigned int eip;
	unsigned int eflags;
	unsigned int eax,ecx,edx,ebx;
	unsigned int esp;
	unsigned int ebp;
	unsigned int esi;
	unsigned int edi;
	unsigned short es,__esh;
	unsigned short cs,__csh;
	unsigned short SS,__ssh;
	unsigned short ds,__dsh;
	unsigned short fs,__fsh;
	unsigned short gs,__gsh;
	unsigned short ldtr,__ldtrh;
	unsigned short trace,IO_bitmap_offset;
	unsigned int bitmap_io_permission[8192/32];
};

extern struct x86_TSS *TSS;
struct gdt_descriptor {
	unsigned short int limit0_15;
	unsigned short int base0_15;
	unsigned char base16_23;
	unsigned char access;
	unsigned int limit_16_19:4;
	unsigned int flags_nybble:4;
	unsigned char base24_31;
};
extern struct gdt_descriptor *GDT;

#define D_PRESENT	0x80
#define LIV0		0x00
#define	LIV1		0x20
#define LIV2		0x40
#define LIV3		0x60

#define S			0x10
#define EXECUTABLE	0x8
#define EXPANSION	0x4
#define GRANU		0x8
#define DEFAULT		0x4

#define STANDARD_CODE_SEGMENT (D_PRESENT | S | EXECUTABLE | WRITE_READ )
#define STANDARD_DATA_SEGMENT (D_PRESENT | S  | WRITE_READ )
#define KERNEL_CODE_SEGMENT (STANDARD_CODE_SEGMENT | DPL_0)
#define KERNEL_DATA_SEGMENT  (STANDARD_DATA_SEGMENT | DPL_0)
#define USER_CODE_SEGMENT (STANDARD_CODE_SEGMENT | DPL_3)
#define USER_DATA_SEGMENT  (STANDARD_DATA_SEGMENT | DPL_3)
#define TSS_SEGMENT ( D_PRESENT | DPL_0 | EXECUTABLE | 1)
#define DEFAULT_NYBBLE_FLAGS (GRANULARITY | DEFAULT_SIZE)
#define TSS_NYBBLE_FLAGS 0
#define KERNEL_CODE		0x08
#define KERNEL_DATA		0x10
#define USER_CODE		0x18
#define USER_DATA		0x20
#define SUPERVISOR_PRIVILEGE 0
#define USER_PRIVILEGE 3
#define KERNEL_CODE_SELECTOR	KERNEL_CODE
#define KERNEL_DATA_SELECTOR	KERNEL_DATA
#define USER_CODE_SELECTOR	USER_CODE | USER_PRIVILEGE
#define USER_DATA_SELECTOR 	USER_DATA | USER_PRIVILEGE

void load_GDT(struct gdt_descriptor* base,unsigned num_desc);

unsigned int add_GDT(unsigned int base, unsigned int limit, unsigned char access, unsigned char (flags_nybble);

void remove_GDT_entry(unsigned int sel);

void initGDT(void);
